<?php
/**
 * Created by PhpStorm.
 * User: yf
 * Date: 2018/10/26
 * Time: 5:39 PM
 */

namespace App\HttpController\Api\VersionOne;

use App\Model\ActivityApplyModel;
use App\Model\ActivityModel;
use App\Model\CouponsGroupLogModel;
use App\Model\RewardOrderModel;
use App\Model\UserModel;
use App\Model\UserMoneyLogModel;
use App\Model\UserMoneyModel;
use App\Model\UserPartakeModel;
use App\Model\WithdrawOrderModel;
use App\Utility\CommonTool;
use EasySwoole\Http\Message\Status;
use EasySwoole\HttpAnnotation\AnnotationTag\Param;
use EasySwoole\HttpAnnotation\AnnotationTag\Method;
use EasySwoole\Mysqli\QueryBuilder;
use EasySwoole\ORM\DbManager;
use EasySwoole\ORM\Exception\Exception;
use EasySwoole\Pool\Exception\PoolEmpty;
use Throwable;

class User extends VersionBase
{
    /**
     * 检查新用户大礼包
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function checkNewcomer()
    {
        $userId = $this->input('user_id', 0);
        if ($userId < 0) {
            $this->writeJson(Status::CODE_UNAUTHORIZED, '', '用户ID出错');
            return false;
        } elseif ($userId == 0) {
            $this->writeJson(Status::CODE_OK, [
                'newcomer' => 0,
            ], "success");
            return false;
        }

        $newcomer = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return CouponsGroupLogModel::invoke($client)->where('user_id', $userId)->where('group_id', 1)->get();
        });

        if ($newcomer) {
            if ((intval($newcomer->create_time) + (86400 * 3)) >= time()) {
                $newcomerBoolean = 1; // 可以领取新用户大礼包
            } else {
                $newcomerBoolean = 0; // 不可以领取新用户大礼包
            }
        } else {
            $newcomerBoolean = 0; // 不可以领取新用户大礼包
        }

        return $this->writeJson(Status::CODE_OK, [
            'newcomer' => $newcomerBoolean,
        ], "success");
    }

    /**
     * 获取用户基本信息
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function getUserInfo()
    {
        $userId = $this->input('user_id', 0);
        $userInfo = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return UserModel::invoke($client)->get($userId);
        });
        if (!$userInfo) {
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "获取该用户信息失败");
        } else {
            // 获取用户剩余金额
            $userMoney = DbManager::getInstance()->invoke(function ($client) use ($userInfo) {
                return UserMoneyModel::invoke($client)->where('user_id', $userInfo->id)->val('balance');
            });

            // 获取用户累计奖金
            $userPrizeMoneyTotalList = DbManager::getInstance()->invoke(function ($client) use ($userId) {
                return UserMoneyLogModel::invoke($client)->where('user_id', $userId)->where('type', 1)->sum('money_change');
            });
            // 获取用户当日奖金
            $todayTimeBegin = strtotime(date('Y-m-d'));
            $todayTimeEnd = $todayTimeBegin + 86400 - 1;
            $userPrizeMoneyTodayList = DbManager::getInstance()->invoke(function ($client) use ($userId, $todayTimeBegin, $todayTimeEnd) {
                $userMoneyLogModel = UserMoneyLogModel::invoke($client);
                $userMoneyLogModel->changeTableName($userId);
                $userMoneyLogModel->where('user_id', $userId);
                $userMoneyLogModel->where('type', 1);
                $userMoneyLogModel->where('create_time', [$todayTimeBegin, $todayTimeEnd], 'between');
                return $userMoneyLogModel->sum('money_change');
            });
            // 获取用户参赛记录
            $userPartakeList = DbManager::getInstance()->invoke(function ($client) use ($userId) {
                return UserPartakeModel::invoke($client)->where('user_id', $userId)->get();
            });

            if ($userPartakeList) {
                $res['partake_num'] = $userPartakeList->partake_num; //参数次数
                $res['finish_num'] = $userPartakeList->finish_num;  //完成的次数
                $res['finish_percent'] = $userPartakeList->finish_percent; //完成率
            } else {
                $res['partake_num'] = 0;
                $res['finish_num'] = 0;
                $res['finish_percent'] = 0;
            }
            // 获取用户的排名
            $rank = DbManager::getInstance()->invoke(function ($client) {
                return UserPartakeModel::invoke($client)->field(['user_id'])->order('finish_percent', 'asc')->all();
            });
            $count = count($rank);
            $userRank = 0;
            foreach ($rank as $k => $v) {
                if ($v->user_id == $userId) {
                    $userRank = $k + 1;
                    break;
                }
            }
            if ($userRank != 0) {
                $rankPercent = round(($userRank / $count) * 100, 2);
            } else {
                $rankPercent = 0;
            }

            $res['user_id'] = $userId;
            $res['faceimg_url'] = $userInfo->headimg_url;
            $res['nick_name'] = $userInfo->nick_name;
            $res['sex'] = $userInfo->sex;
            $res['create_time'] = $userInfo->create_time;
            $res['user_money'] = ($userMoney ? $userMoney : 0); // 用户余额
            $res['today_prize_money'] = ($userPrizeMoneyTodayList ? $userPrizeMoneyTodayList : 0); // 今天奖励
            $res['total_prize_money'] = ($userPrizeMoneyTotalList ? $userPrizeMoneyTotalList : 0); // 累计奖励
            $res['rank_percent'] = ($rankPercent ? $rankPercent : 0); // 排行
            return $this->writeJson(Status::CODE_OK, $res, "success");
        }
    }

    /**
     * 获取用户交易记录
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @Param(name="pn", alias="分页", integer="", min="1", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function getUserTransactionDetail()
    {
        $userId = $this->input('user_id', 0);
        $pn = $this->input('pn', 1);

        $count = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return UserMoneyLogModel::invoke($client)->changeTableName($userId)->where('user_id', $userId)->count();
        });
        $limit = ($pn - 1) * 50;
        $totalPage = intval(ceil($count / 50));
        if ($pn > $totalPage) {
            $this->writeJson(Status::CODE_BAD_GATEWAY, [], "没有更多了~");
            return false;
        }

        $list = DbManager::getInstance()->invoke(function ($client) use ($userId, $limit) {
            return UserMoneyLogModel::invoke($client)
                ->changeTableName($userId)
                ->field(['money_change', 'type', 'create_time', 'info'])
                ->where('user_id', $userId)
                ->order('create_time', 'desc')
                ->limit($limit, 50)
                ->all();
        });

        $res = [];
        if ($list) {
            foreach ($list as $k => $v) {
                $r = [];
                $r['money_change'] = $v->money_change;
                $r['type'] = $v->type;
                $r['create_time'] = $v->create_time;
                $r['info'] = $v->info;
                $res[] = $r;
            }
        }

        return $this->writeJson(Status::CODE_OK, [
            'total' => $totalPage,
            'per_page' => intval(50),
            'current_page' => intval($pn),
            'last_page' => $totalPage,
            'is_last_page' => intval(($pn == $totalPage ? 1 : 0)),
            'data' => $res,
        ], "success");
    }

    /**
     * 获取用户提现记录
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @Param(name="pn", alias="分页", integer="", min="1", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function getUserWithdrawList()
    {
        $userId = $this->input('user_id', 0);
        $pn = $this->input('pn', 0);

        $count = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return WithdrawOrderModel::invoke($client)->where('user_id', $userId)->count();
        });
        $limit = ($pn - 1) * 50;
        $totalPage = intval(ceil($count / 50));
        if ($pn > $totalPage) {
            $this->writeJson(Status::CODE_BAD_GATEWAY, [], "没有更多了~");
            return false;
        }

        $list = DbManager::getInstance()->invoke(function ($client) use ($userId, $limit) {
            return WithdrawOrderModel::invoke($client)->where('user_id', $userId)->limit($limit, 50)->all();
        });
        $res = [];
        if ($list) {
            foreach ($list as $k => $v) {
                $r = [];
                $r['withdraw_amount'] = $v->withdraw_amount;
                $r['status'] = $v->status;
                if ($v->commission > 0) {
                    $msg = '手续费' . $v->commission . '、实际到账' . $v->true_money;
                    $r['create_time'] = $v->create_time . '　　　' . $msg;
                    $r['update_time'] = $v->update_time . '　　　' . $msg;
                } else {
                    $r['create_time'] = $v->create_time;
                    $r['update_time'] = $v->update_time;
                }

                $res[] = $r;
            }
        }

        return $this->writeJson(Status::CODE_OK, [
            'total' => $totalPage,
            'per_page' => intval(50),
            'current_page' => intval($pn),
            'last_page' => $totalPage,
            'is_last_page' => intval(($pn == $totalPage ? 1 : 0)),
            'data' => $res,
        ], "success");
    }

    /**
     * 获取用户参赛记录
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @Param(name="pn", alias="分页", integer="", min="1", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function getUserHistory()
    {
        $userId = $this->input('user_id', 0);
        $pn = $this->input('pn', 0);

        $count = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return ActivityApplyModel::invoke($client)->changeTableName($userId)->where('user_id', $userId)->count();
        });
        $limit = ($pn - 1) * 50;
        $totalPage = intval(ceil($count / 50));
        if ($pn > $totalPage) {
            $this->writeJson(Status::CODE_BAD_GATEWAY, [], "没有更多了~");
            return false;
        }

        $list = DbManager::getInstance()->invoke(function ($client) use ($userId, $limit) {
            return ActivityApplyModel::invoke($client)
                ->changeTableName($userId)
                ->field(['activity_id', 'create_time', 'update_time', 'sign_time', 'target_time', 'status'])
                ->where('user_id', $userId)
                ->order('id', 'desc')
                ->limit($limit, 50)
                ->all();
        });
        $res = [];
        if ($list) {
            foreach ($list as $k => $v) {
                $money = '?';
                $r = [];
                $r['activity_id'] = $v->activity_id;
                if ($v->update_time) {
                    $r['up_time'] = $v->update_time;
                } else {
                    $r['up_time'] = $v->create_time;
                }

                $beginTime = DbManager::getInstance()->invoke(function ($client) use ($userId, $v) {
                    return ActivityModel::invoke($client)->get($v->activity_id);
                });
                $r['title'] = CommonTool::getTypeName($beginTime->btype_id, 1) . '(' . CommonTool::getTypeName($beginTime->stype_id, 2) . ')-' . mb_substr($beginTime->name, 4) . '期'; // 标题

                if (time() < strtotime($beginTime->start_date . ' ' . $beginTime->start_time)) {
                    $money = '?';
                    $r['status'] = 3; //活动待开始
                    $r['alert_msg'] = '待完成';
                } else {
                    if ($v->target_time == $v->sign_time && $v->status == 0) {
                        $money = '?';
                        $r['status'] = 4; // 已完成待开奖
                        $r['alert_msg'] = '待开奖';
                    } else {
                        $r['status'] = $v->status;
                        switch ($v->status) {
                            case 0 : // 待完成的
                                $todayEndTimeStamp = strtotime(date('Y-m-d') . ' ' . $beginTime->end_time); // 获取最后签到时间戳
                                $needSignNumber = (strtotime(date('Y-m-d')) - strtotime($beginTime->start_date)) / 86400; // 获取应该签到的日期(今天尚未打卡)
                                if ($todayEndTimeStamp < time()) {
                                    // 超过打卡时间,应该打卡
                                    $needSignNumber = $needSignNumber + 1;
                                }
                                if ($needSignNumber > $v->sign_time) {
                                    $money = '+0.00';
                                    $r['status'] = 2;
                                    $r['alert_msg'] = '失败';
                                } else {
                                    $money = '?';
                                    $r['status'] = 0;
                                    $r['alert_msg'] = '待完成';
                                }
                                break;
                            case 1 : // 已完成已开奖
                                $reward = DbManager::getInstance()->invoke(function ($client) use ($userId, $v) {
                                    return RewardOrderModel::invoke($client)
                                        ->changeTableName($userId)
                                        ->where('user_id', $userId)
                                        ->where('activity_id', $v->activity_id)
                                        ->get();
                                });
                                if ($reward) {
                                    $money = '+' . $reward->reward;
                                    $r['alert_msg'] = '成功';
                                } else {
                                    $money = '?';  //未开奖
                                    $r['alert_msg'] = '待开奖';
                                }
                                $r['status'] = 1;
                                break;
                            case 2 : // 参与失败的
                                $money = '+0.00';
                                $r['status'] = 2;
                                $r['alert_msg'] = '失败';
                                break;
                        }
                    }

                }

                $r['money'] = $money;
                $res[] = $r;

            }
        }

        return $this->writeJson(Status::CODE_OK, [
            'total' => $totalPage,
            'per_page' => intval(50),
            'current_page' => intval($pn),
            'last_page' => $totalPage,
            'is_last_page' => intval(($pn == $totalPage ? 1 : 0)),
            'data' => $res,
        ], "success");
    }

    /**
     * 用户提现下行
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @Param(name="open_id", alias="微信openid", lengthMax="32", length="32", required="", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function withdrawListDown()
    {
        $userId = $this->input('user_id', 0);
        $user = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            $userModel = UserModel::invoke($client);
            $field = [
                'u.id',
                'u.nick_name',
                'u.real_name',
                'u.withdrawal_account',
                'u.phone',
                'm.balance',
            ];
            return $userModel->field($field)
                ->where('u.id', $userId)
                ->alias('u')
                ->join('user_money m', 'm.user_id = u.id')
                ->get();
        });

        if (!$user) {
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "用户登录信息错误");
        } else {
            return $this->writeJson(Status::CODE_OK, $user->toArray(), "success");
        }
    }

    /**
     * 用户提现上行
     * @Method(allow={POST})
     * @Param(name="user_id", alias="用户ID", integer="", min="1", required="", notEmpty="不能为空")
     * @Param(name="open_id", alias="微信openid", lengthMax="32", length="32", required="", notEmpty="不能为空")
     * @Param(name="real_name", alias="真实姓名", required="", notEmpty="不能为空")
     * @Param(name="phone", alias="手机号码", numeric="", lengthMax="13", required="", allDigital="", notEmpty="不能为空")
     * @Param(name="money", alias="提取金额", money="", min="10.00", max="500.00", required="", notEmpty="不能为空")
     * @Param(name="type", alias="提取类型", between="1,2", integer="", required="", notEmpty="不能为空")
     * @Param(name="withdrawal_account", alias="提取账号", notEmpty="不能为空")
     * @throws Exception
     * @throws PoolEmpty
     * @throws Throwable
     */
    public function withdrawListUp()
    {
        $userId = $this->input('user_id', 0);
        $realName = $this->input('real_name', '');
        $phone = $this->input('phone', 0);
        $money = $this->input('money', '');
        $handleType = $this->input('type', 1);
        $withdrawalAccount = $this->input('withdrawal_account', '');

        if (!in_array($handleType, [1, 2])) {
            $this->writeJson(Status::CODE_BAD_GATEWAY, [], "请选择提现方式");
            return false;
        }
        if ($handleType == 2 && !$withdrawalAccount) {
            $this->writeJson(Status::CODE_BAD_GATEWAY, [], "请填写支付宝账号");
            return false;
        }

        /* 加锁,防止用户多次提交 */
        $lockRes = CommonTool::redisLock('withdrawList_' . $userId);
        if (!$lockRes) {
            return $this->writeJson(Status::CODE_BAD_REQUEST, [], '请勿重复请求~');
        }

        $user = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            $userModel = UserModel::invoke($client);
            $field = [
                'u.id',
                'u.nick_name',
                'u.real_name',
                'u.withdrawal_account',
                'u.phone',
                'm.balance',
            ];
            return $userModel->where('u.id', $userId)
                ->field($field)
                ->alias('u')
                ->join('user_money m', 'm.user_id = u.id')->get();
        });
        if (!$user) {
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "用户登录信息错误");
        }
        if ($user->balance < $money) {
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "提现额度超过可用额度");
        }

        $beforeMoney = floatval($user->balance);
        if (floatval($user->balance - $money) < 0) {
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "余额不足");
        }

        $lastWithdrawOrderTime = DbManager::getInstance()->invoke(function ($client) use ($userId) {
            return WithdrawOrderModel::invoke($client)->where('user_id', $userId)->order('id', 'desc')->limit(1)->val('create_time');
        });
        if ($lastWithdrawOrderTime) {
            $today = strtotime(date('Y-m-d'));
            $lastDay = strtotime(date('Y-m-d', $lastWithdrawOrderTime));
            if ($today - $lastDay < 86400) {
                return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "今日提现次数已用完");
            }
        }

        try {
            //开启事务
            DbManager::getInstance()->startTransaction();

            if ((!$user->phone && $phone)) {
                $user->phone = $phone;
            }
            if ((!$user->real_name && $realName)) {
                $user->real_name = $realName;
            }
            if ($handleType == 2) {
                if ((!$user->withdrawal_account && $withdrawalAccount)) {
                    $user->withdrawal_account = $withdrawalAccount;
                }
            }
            $user->update_time = time();
            $user->update();

            UserMoneyModel::create()->updateUserMoney($userId, [
                'balance' => ['dec', $money],
            ]);

            $commission = round(($money * 0.01), 2);
            if ($commission < 1) {
                $commission = 1.00;
            }

            $withdrawNewOrderObj = WithdrawOrderModel::create()->addWithdrawOrder($userId, $money, $handleType, $commission, round(($money - $commission), 2));

            UserMoneyLogModel::create()->add($userId, $beforeMoney, ($money * -1), 3, $withdrawNewOrderObj->id, '提现');
        } catch (Throwable  $e) {
            // 回滚事务
            DbManager::getInstance()->rollback();
            var_dump($e->getMessage());
            CommonTool::redisUnlock('withdrawList_' . $userId);
            return $this->writeJson(Status::CODE_BAD_GATEWAY, [], "网络繁忙,请稍后再试");
        } finally {
            // 提交事务
            DbManager::getInstance()->commit();
            CommonTool::redisUnlock('withdrawList_' . $userId);
            return $this->writeJson(Status::CODE_OK, [], "success");
        }
    }
}